package com.sntra.beibi.service.impl;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.imageio.ImageIO;

import org.apache.commons.imaging.ImageFormats;
import org.apache.commons.imaging.Imaging;
import org.apache.commons.imaging.ImagingConstants;
import org.apache.commons.imaging.PixelDensity;
import org.apache.commons.imaging.formats.png.PhysicalScale;
import org.apache.commons.imaging.formats.png.PngConstants;
import org.apache.commons.imaging.formats.png.PngImageInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.sntra.beibi.common.DotUtils;
import com.sntra.beibi.dao.BookMapper;
import com.sntra.beibi.dao.DotMapper;
import com.sntra.beibi.dao.LearnBookMapper;
import com.sntra.beibi.dao.LearnPageMapper;
import com.sntra.beibi.dao.PageMapper;
import com.sntra.beibi.dao.PenMapper;
import com.sntra.beibi.domain.Book;
import com.sntra.beibi.domain.Dot;
import com.sntra.beibi.domain.LearnBook;
import com.sntra.beibi.domain.LearnPage;
import com.sntra.beibi.domain.Page;
import com.sntra.beibi.domain.Pen;
import com.sntra.beibi.service.DotService;
import com.sntra.beibi.service.DrawService;

@Service
public class DotServiceImpl implements DotService {

    @Autowired
    private DotMapper dotMapper;
        
    @Autowired
    private PageMapper pageMapper;
    
    @Autowired
    private BookMapper bookMapper;
    
    @Autowired
    private PenMapper penMapper;
    
    @Autowired
    private LearnPageMapper lpMapper;
    
    @Autowired
    private LearnBookMapper lbMapper;
    
    @Autowired
    private DrawService mPen;
	//private PenService mPen;
    
    @Value("${img.rootdir}")
	private String dir;
    
	@Autowired
	private StringRedisTemplate stringRedisTemplate;
    
	@Override
	public List<Dot> selectDots(String penMac, int bookID, int pageID, int status) {
		// TODO Auto-generated method stub
		return dotMapper.selectDots(penMac, bookID, pageID,status);
	}
	
	@Override
	public List<Dot> selectDotsByUser(int ownerID,  int bookID, int pageID, int status) {
		// TODO Auto-generated method stub
		return dotMapper.selectDotsByUser(ownerID, bookID, pageID,status);
	}
	
	public int updateStatusBatch(List<Integer> dotIds) {
		return dotMapper.updateStatusBatch(dotIds);
	}
	
	@Transactional 
	@Async
	public String draw(int ownerID, int bookID, int pageID, String penMac) {
		    Pen pen = penMapper.selectByMac(penMac);
		    if(pen == null || pen.getUserId()==null) {
		    	stringRedisTemplate.opsForValue().set("isDrawPdf_"+penMac,"0", 60 , TimeUnit.SECONDS);
		    	return "Error"; //没有对应用户的暂不处理
		    }
		    ownerID = pen.getUserId();
		    LearnPage lp = lpMapper.selectPageByKeyinfo(ownerID,bookID,pageID);
		    String imgUrl = null;
		    if(lp!=null) {
				imgUrl = lp.getImgUrl();
		    }  
	    	String tmpFileName  = null; 
	    	Page ps = pageMapper.selectPageByBookIdAndPageNo(bookID, pageID);
	    	Date now = new Date();
	    	String destDir = dir + bookID + "/" + ownerID + "/";
    		File df = new File(destDir);
    		String learnUrl = destDir + pageID +"_" + now.getTime() + ".png";
			try {
				if(!StringUtils.hasText(imgUrl)) {
		    		if(!df.exists()) {
		    			df.mkdirs();
		    		}
		    		LearnBook lb = lbMapper.selectLearnBook(bookID, ownerID);
		    		if(lb==null) {
		    			lb = new LearnBook();
		    			Book b = bookMapper.selectByPrimaryKey(bookID);
		    			BeanUtils.copyProperties(b, lb);
		    			lb.setId(null);
		    			lb.setLearnerId(ownerID);
		    			lb.setBookId(bookID);
		    			lbMapper.insert(lb);
		    			lb = lbMapper.selectLearnBook(bookID, ownerID);
		    		}
		    		if(lp == null) {
	    		    	lp = new LearnPage();
	    		    	lp.setLearnerId(ownerID);
	    		    	lp.setBookId(bookID);
	    		    	lp.setLearnBookId(lb.getId());
	    		    	lp.setPageId(ps.getId());
	    		    	lp.setPageNo(pageID);
	    		    	lp.setName(ps.getName());
	    		    	lp.setIntroduction(ps.getIntroduction());
	    		    	lp.setUrl("");
	    		    	lp.setCreateTime(now);
	    		    	lp.setUpdateTime(now);
	    		    	lp.setImgUrl(learnUrl);
	    		    	lpMapper.insert(lp);
		    		} else {
		    			lp.setImgUrl(learnUrl);
		    		}
		    		 tmpFileName = ps.getImgUrl();
		    	} else {
		    		tmpFileName = imgUrl;
		    	}
				File tmpPng = new File(tmpFileName);
			    DotUtils.createDirectory(tmpPng.getParent());
			    BufferedImage oriImage = ImageIO.read(tmpPng);
			    //生产画板
		        Graphics2D graphics = oriImage.createGraphics();
				PngImageInfo  imageInfo = (PngImageInfo)Imaging.getImageInfo(new File(ps.getImgUrl()));
				float dpi = imageInfo.getPhysicalHeightDpi();
				mPen.transformWidth(1.0f, dpi);
				
	            float paperHeight = imageInfo.getPhysicalHeightInch() * DotUtils.IN_SIZE; 
	            int height = oriImage.getHeight();
	            
				List<Dot> dots = dotMapper.selectDots(penMac, bookID, pageID, 0);
				List<Integer> dotIds = new ArrayList<Integer>();
	            for(Dot dot : dots) {
	            	mPen.processDot(dot, height, paperHeight, graphics);
	            	dotIds.add(dot.getDotId());
	            }
	            if(dotIds.size()>0) {
	            	dotMapper.updateStatusBatch(dotIds);
	            }
	            ImageIO.write(oriImage, "PNG", new File(learnUrl));
		        lp.setDoStatus(1);
		        lp.setImgUrl(learnUrl); //将生成图片置空
		        lp.setImgStatus(1); //重新再生成
		        lpMapper.updateStatusAndUrl(lp);
		        if(StringUtils.hasText(imgUrl)) {
			        File oldFile = new File(imgUrl);
			        if(oldFile.exists()) {
			        	oldFile.delete();
			        }
		        }
		        stringRedisTemplate.opsForValue().set("isDrawPdf_"+penMac,"0", 60 , TimeUnit.SECONDS);
		        Thread.sleep(1000);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return "OK";
		}
    /**
	@Transactional 
	@Async
	public String draw(int ownerID, int bookID, int pageID, String penMac) {
		    Pen pen = penMapper.selectByMac(penMac);
		    if(pen == null || pen.getUserId()==null) {
		    	stringRedisTemplate.opsForValue().set("isDrawPdf_"+penMac,"0", 60 , TimeUnit.SECONDS);
		    	return "Error"; //没有对应用户的暂不处理
		    }
		    ownerID = pen.getUserId();
		    LearnPage lp = lpMapper.selectPageByKeyinfo(ownerID,bookID,pageID);
		    String url = null;
		    if(lp!=null) {
				url = lp.getUrl();
		    }  
	    	PdfDocument pdf = null;
	    	String tmpFileName  = null; 
	    	Page ps = pageMapper.selectPageByBookIdAndPageNo(bookID, pageID);
			try {
				if(StringUtils.isEmptyOrWhitespaceOnly(url)) {
		    		url = ps.getUrl();
		    		String destDir = dir + bookID + "/" + ownerID + "/";
		    		File df = new File(destDir);
		    		if(!df.exists()) {
		    			df.mkdirs();
		    		}
		    		LearnBook lb = lbMapper.selectLearnBook(bookID, ownerID);
		    		if(lb==null) {
		    			lb = new LearnBook();
		    			Book b = bookMapper.selectByPrimaryKey(bookID);
		    			BeanUtils.copyProperties(b, lb);
		    			lb.setId(null);
		    			lb.setLearnerId(ownerID);
		    			lb.setBookId(bookID);
		    			lbMapper.insert(lb);
		    			lb = lbMapper.selectLearnBook(bookID, ownerID);
		    		}
		    		String learnUrl = destDir + pageID + ".pdf";
		    		if(lp == null) {
	    		    	lp = new LearnPage();
	    		    	lp.setLearnerId(ownerID);
	    		    	lp.setBookId(bookID);
	    		    	lp.setLearnBookId(lb.getId());
	    		    	lp.setPageId(ps.getId());
	    		    	lp.setPageNo(pageID);
	    		    	lp.setName(ps.getName());
	    		    	lp.setIntroduction(ps.getIntroduction());
	    		    	Date now = new Date();
	    		    	lp.setCreateTime(now);
	    		    	lp.setUpdateTime(now);
	    		    	lp.setUrl(learnUrl);
	    		    	lpMapper.insert(lp);
		    		} else {
		    			lp.setUrl(learnUrl);
		    		}
		    		 tmpFileName = learnUrl+"tmp.pdf";
		    	} else {
		    		tmpFileName = url +"tmp.pdf";
		    	}
				File desPdf = new File(url);
			    DotUtils.createDirectory(desPdf.getParent());
				PdfReader reader = new PdfReader(desPdf);
				File tmpFile = new File(tmpFileName);
		    	PdfWriter writer = new PdfWriter(tmpFile);
				pdf = new PdfDocument(reader,writer);
				PdfPage pp = pdf.getFirstPage();
				Rectangle pageSize = pp.getPageSize();
				float height =  pageSize.getHeight();
				float width = pageSize.getWidth();

				File file = new File(ps.getImgUrl());
				PngImageInfo  imageInfo = (PngImageInfo)Imaging.getImageInfo(file);
				float dpi = imageInfo.getPhysicalHeightDpi();

				PdfCanvas canvas = new PdfCanvas(pp);
				mPen.transformWidth(1.0f, 72f);
		        
	            float paperHeight = imageInfo.getPhysicalHeightInch() * DotUtils.IN_SIZE; 
	            
				List<Dot> dots = dotMapper.selectDots(penMac, bookID, pageID, 0);
				List<Integer> dotIds = new ArrayList<Integer>();
	            for(Dot dot : dots) {
	            	mPen.processDot(dot, (int)height, paperHeight, canvas, width, height);
	            	dotIds.add(dot.getDotId());
	            }
	            if(dotIds.size()>0) {
	            	dotMapper.updateStatusBatch(dotIds);
	            }
				canvas.stroke();
		        pdf.close();
		        lp.setDoStatus(1);
		        //lp.setImgUrl(""); //将生成图片置空
		        lp.setImgStatus(0); //重新再生成
		        lpMapper.updateStatusAndUrl(lp);
		        File oldFile = new File(lp.getUrl());
		        if(oldFile.exists()) {
		        	oldFile.delete();
		        }
		        tmpFile.renameTo(new File(lp.getUrl()));
		        stringRedisTemplate.opsForValue().set("isDrawPdf_"+penMac,"0", 60 , TimeUnit.SECONDS);
		        Thread.sleep(1000);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			return "OK";
		}
	*/
	@Override
	public Pen getPen(String penMac) {
		return penMapper.selectByMac(penMac);
	}
	
	public int savePen(Pen pen) {
		return penMapper.insert(pen);
	}
	
	public int updatePen(Pen pen) {
		return penMapper.updateByPrimaryKey(pen);
	}

	@Override
	public int insertBatch(List<Dot> dots) {
		// TODO Auto-generated method stub
		return dotMapper.insertBatch(dots);
	}

	@Override
	public int count(int sectionID, int ownerID, int bookID, int pageID) {
		// TODO Auto-generated method stub
		return dotMapper.count(sectionID, ownerID, bookID, pageID);
	}
	
}
